#include "Socket.hpp"
#include <sys/epoll.h>

using namespace sock_ns;

class EpollServer
{

public:
    static const int gnum = 64;

    EpollServer(uint16_t port)
        :_port(port)
        ,_ListenSock(std::make_unique<TcpSocket>())
    {
        //1.创建listensock
        InetAddr addr("0",port);
        _ListenSock->BuildListenSocket(addr);
        
        //2.创建epoll模型
        _epfd = epoll_create(128);//size不重要
        if(_epfd<0)
        {
            Log(FATAL, "epoll_create error\n");
            exit(5);
        }
        Log(DEBUG, "epoll_create success, epfd: %d\n", _epfd);//创建成功

        struct epoll_event ev;
        ev.events = EPOLLIN;//对于读文件事件
        ev.data.fd = _ListenSock->SockFd();
        int n = epoll_ctl(_epfd,EPOLL_CTL_ADD,_ListenSock->SockFd(),&ev);//增加对于fd的even事件的关注

    }


    void HandlerEvent(int n)
    {
        //一共有n个事件待处理
        for(int i=0;i<n;i++)
        {
            uint32_t event = _events[i].events;
            int sockfd = _events[i].data.fd;
            if(event==EPOLLIN)
            {
                if(sockfd==_ListenSock->SockFd())
                {
                    //如果是listen套接字
                    InetAddr clientaddr;
                    int newfd = _ListenSock->Accepter(&clientaddr);
                    //把新的fd加入到epoll_ctl中
                    struct epoll_event ev;
                    ev.events = EPOLLIN;//对于读文件事件
                    ev.data.fd = newfd;
                    epoll_ctl(_epfd,EPOLL_CTL_ADD,newfd,&ev);
                }
                else
                {
                    //读取数据
                    char buffer[1024];
                    ssize_t n =read(sockfd,buffer,sizeof(buffer));
                    if(n>0)
                    {
                        Log(DEBUG, "normal fd %d ready, recv begin...\n", sockfd);
                        buffer[n] = 0;
                        std::cout << "client say# " << buffer << std::endl;

                        std::string echo_string = "server echo# ";
                        echo_string += buffer;
                        write(sockfd, echo_string.c_str(), echo_string.size());
                    }
                    else if(n==0)
                    {
                        Log(DEBUG,"client %d fd close,me too!",sockfd);
                        epoll_ctl(_epfd,EPOLL_CTL_DEL,sockfd,nullptr);//事件可以设为空
                        close(sockfd);
                    }
                    else
                    {
                        //出错了把epfd和sockfd都删除
                        Log(FATAL,"%d fd error,closing!",sockfd);
                        epoll_ctl(_epfd,EPOLL_CTL_DEL,sockfd,nullptr);//事件可以设为空
                        close(sockfd);
                    }
                } 
            }

            
        }

    }

    void Loop()
    {
        while(1)
        {
            int timeout = 1000;//单位是毫秒
            int n = epoll_wait(_epfd,_events,gnum,timeout);
            switch(n)
            {
            case 0:
                Log(DEBUG,"epoll_wait time out...");
                break;
            case -1:
                Log(FATAL,"epoll_wait error...");
                break;
            default:
                HandlerEvent(n);
                //cout<<"Handlering..\n";
                Log(DEBUG,"epoll_wait success ,%d events is ready",n);
                break;
            }
        }
    }


    ~EpollServer()
    {
        //首先关闭epfd,再关闭fd
        _ListenSock->Close();
        if(_epfd>0)
            close(_epfd);
    }

    
private:
    uint16_t _port;//端口号
    std::unique_ptr<Socket> _ListenSock;
    int _epfd;

    struct epoll_event _events[gnum];
};